package com.briup.run.service.impl;

import com.briup.run.bean.Graderecord;
import com.briup.run.bean.Memberinfo;
import com.briup.run.bean.Pointaction;
import com.briup.run.bean.Pointrecord;
import com.briup.run.constant.PointActionConstant;
import com.briup.run.dao.GraderecordMapper;
import com.briup.run.dao.MemberinfoMapper;
import com.briup.run.dao.PointactionMapper;
import com.briup.run.dao.PointrecordMapper;
import com.briup.run.exception.CustomerException;
import com.briup.run.service.MemberInfoService;
import com.briup.run.util.MD5Util;
import com.briup.run.util.MailUtil;
import com.briup.run.util.RandomUtil;
import com.briup.run.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Auther: vanse(lc))
 * @Date: 2022/10/6-10-06-14:43
 * @Description：会员服务类
 */
public class MemberInfoServiceImpl implements MemberInfoService {
    // 线程不安全

    @Override
    public void regsiter(Memberinfo memberinfo) {
        // md5加密密码
        memberinfo.setPassword(MD5Util.encode(memberinfo.getPassword()));

        SqlSession session = SqlSessionUtil.openSession();
        MemberinfoMapper memberInfoMapper = session.getMapper(MemberinfoMapper.class);
        PointactionMapper pointActionMapper = session.getMapper(PointactionMapper.class);
        PointrecordMapper pointRecordMapper = session.getMapper(PointrecordMapper.class);
        GraderecordMapper graderecordMapper = session.getMapper(GraderecordMapper.class);

        try {
            // 1.校验昵称是否唯一  TODO MD5加密
            String nickname = memberinfo.getNickname();
            Memberinfo miDB = getMebmerInfoByName(memberInfoMapper, nickname);
            if (miDB != null) {
                // 昵称存在
                throw new CustomerException("昵称已存在");
            }
            // 2.插入会员
            // 2.1 基本信息
            // 2.2 额外信息
            memberinfo.setRegisterdate(new Date());
            memberinfo.setLatestdate(null); // 上一次登录
            memberinfo.setStatus(0L); // 数据库默认值 0 正常 1注销
            memberinfo.setIsonline(0L);
            // 根据当前动作 去 ActionPoint查分数
            Pointaction action = pointActionMapper.findByActionname(PointActionConstant.REGISTER);
            memberinfo.setPoint(0L + action.getPoint()); // 注册加分数 TODO
            // 根据当前分数 去判断等级 GradePoint
            Graderecord graderecord = graderecordMapper.findGradeByPoint(memberinfo.getPoint());
            memberinfo.setGraderecord(graderecord);
            // 分数记录 PointRecord
            Pointrecord pointRecord = Pointrecord.builder()
                    .nickname(nickname)
                    .receivedate(new Date())
                    .pointactionid(action.getId())
                    .build();
            pointRecordMapper.insert(pointRecord);

            // 3.更新推荐人的信息
            String recommender = memberinfo.getRecommender();
            //nickname == null || "".equals(nickname.trim())
            // 注意: 表单 input框 默认是空字符串
            if (recommender != null && !"".equals(recommender.trim())) {
                // 有推荐人 该推荐人必须在数据库存在
                Memberinfo reMemberinfo = getMebmerInfoByName(memberInfoMapper, recommender);
                if (reMemberinfo == null) {
                    throw new CustomerException("无此推荐人");
                }
                // 推荐动作加分
                Pointaction rePointAction = pointActionMapper.findByActionname(PointActionConstant.RECOMMEND);
                // 更新推荐人积分
                reMemberinfo.setPoint(reMemberinfo.getPoint() + rePointAction.getPoint());
                // 最新分数对应的 等级是否变化
                Graderecord reGraderecord = graderecordMapper.findGradeByPoint(reMemberinfo.getPoint());
                reMemberinfo.setGraderecord(reGraderecord);

                // 更新推荐人信息
                memberInfoMapper.updateByPrimaryKeySelective(reMemberinfo);
                // 分数记录
                Pointrecord rePointrecord = Pointrecord.builder()
                        .nickname(recommender)
                        .receivedate(new Date())
                        .pointactionid(rePointAction.getId())
                        .build();
                pointRecordMapper.insert(rePointrecord);
            }
            memberInfoMapper.insert(memberinfo);
            session.commit();
        } catch (CustomerException e) {
            e.printStackTrace();  // catch将CustomerException 抓取了
            session.rollback();
            throw new CustomerException(e.getMessage());
        } finally {
            session.close();
        }
    }

    private Memberinfo getMebmerInfoByName(MemberinfoMapper memberInfoMapper, String nickname) {
        Memberinfo miDB = memberInfoMapper.selectMemberInfoByName(nickname);
        return miDB;
    }

    @Override
    public Memberinfo login(String username, String password) {
        SqlSession session = SqlSessionUtil.openSession();
        Memberinfo memberInfo = null;
        try {
            MemberinfoMapper memberinfoMapper = session.getMapper(MemberinfoMapper.class);
            GraderecordMapper gradeRecordMapper = session.getMapper(GraderecordMapper.class);
            PointactionMapper pointActionMapper = session.getMapper(PointactionMapper.class);
            PointrecordMapper pointRecordMapper = session.getMapper(PointrecordMapper.class);

            // select * from memberinfo where username = #{} and password #{}
            // 1.先查名称  如果查出来 ()
            memberInfo = getMebmerInfoByName(memberinfoMapper, username);
            if (memberInfo == null) {
                throw new CustomerException("用户名有误");
            }
            // 2.判断密码 自定登录 不用比对密码
            if (password == null || !memberInfo.getPassword().equals(password.trim())) {
                throw new CustomerException("密码有误");
            }
            // 同一天登录 加分
            // 判断上一次登录的day和今天的day 不同
            Date latestdate = memberInfo.getLatestdate();
            int day = new Date().getDay();
//            Calendar instance = Calendar.getInstance();
//            instance.setTime(new Date());
//            int day = instance.get(Calendar.DAY_OF_MONTH);
            // 第一次登录 或者 不是同一天登录 加分
            if ((latestdate != null && latestdate.getDay() != day) || latestdate == null) {
                // 不是同一天登录 加分
                Pointaction loginAction = pointActionMapper.findByActionname(PointActionConstant.LOGIN);
                memberInfo.setPoint(memberInfo.getPoint() + loginAction.getPoint());
                // 记录加分记录
                Pointrecord loginPointRecored = Pointrecord.builder()
                        .nickname(memberInfo.getNickname())
                        .receivedate(new Date())
                        .pointactionid(loginAction.getId())
                        .build();
                pointRecordMapper.insert(loginPointRecored);
            }
            // 3.根据分数查等级
            Graderecord graderecord = gradeRecordMapper.findGradeByPoint(memberInfo.getPoint());
            memberInfo.setGraderecord(graderecord);

            memberinfoMapper.updateByPrimaryKeySelective(memberInfo);



            // 部分值要更新 注意: 更新的对象和返回的对象不能是同一个对象
            // 4.更新上一次登录事件  (跟以上操作无关)
            //memberInfo.setLatestdate(new Date());
            Memberinfo newMemeberInfo = Memberinfo.builder()
                    .id(memberInfo.getId())
                    .latestdate(new Date())
                    .isonline(1L)
                    .build();
            // 更新新对象
            memberinfoMapper.updateByPrimaryKeySelective(newMemeberInfo);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            throw new CustomerException(e.getMessage());
        } finally {
            session.close();
        }
        return memberInfo;
    }


    // 退出用户
    @Override
    public void logout(Long id) {
        SqlSession session = SqlSessionUtil.openSession();
        MemberinfoMapper mapper = session.getMapper(MemberinfoMapper.class);
        // 指定退出用户
//        Memberinfo memberinfo = mapper.selectMemberInfoByName(nickName);
        Memberinfo memberinfo = Memberinfo.builder()
                .id(id)
                .isonline(0L)
                .build();
        mapper.updateByPrimaryKeySelective(memberinfo);// 根据id更新
        session.commit();
        session.close();
    }

    /**
     * 更新用户: 将来更新用户
     *
     * @param memberinfo
     */
    @Override
    public void updateMemberInfo(Memberinfo memberinfo) {

    }

    /**
     * 统计在线人数
     *
     * @return 在线人数
     */
    @Override
    public long countOnLine() {
        SqlSession session = SqlSessionUtil.openSession();
        long countOnline;
        try {
            MemberinfoMapper mapper = session.getMapper(MemberinfoMapper.class);
            countOnline = mapper.countOnLine();
        } finally {
            session.close();
        }
        return countOnline;
    }

    /**
     * 统计指定排行积分数据
     *
     * @param num
     * @return
     */
    @Override
    public List<Memberinfo> beforeNumMemberInfo(int num) {
        SqlSession session = SqlSessionUtil.openSession();
        MemberinfoMapper mapper = session.getMapper(MemberinfoMapper.class);
        List<Memberinfo> list = mapper.beforeNumMemberInfo(num);
        session.close();
        return list;
    }

    /**
     * 找回密码
     * @param userName 账户名称
     * @param passwdQuestion 问题
     * @param passwdAnswer 答案
     */
    @Override
    public void foundPass(String userName, String passwdQuestion, String passwdAnswer) {
        SqlSession session = SqlSessionUtil.openSession();
        MemberinfoMapper mapper = session.getMapper(MemberinfoMapper.class);
        Memberinfo memberInfo = getMebmerInfoByName(mapper, userName);
        try {
            if (memberInfo == null) {
                throw new CustomerException("账户名有误");
            }
            if(!memberInfo.getPasswordquestion().equals(passwdQuestion)){
                throw new CustomerException("密保问题有误");
            }
            if(!memberInfo.getPasswordanswer().equals(passwdAnswer)){
                throw new CustomerException("密保答案有误");
            }
            String newPass = RandomUtil.getRandomStr(6);
            // 发邮件
            MailUtil.sendEmails(memberInfo.getEmail(), newPass);
            memberInfo.setPassword(MD5Util.encode(newPass));

            mapper.updateByPrimaryKeySelective(memberInfo);
            session.commit();
        }catch (Exception e){
            session.rollback();
            throw new CustomerException(e.getMessage());
        }finally {
            session.close();
        }
    }
}
